//
//  PlaylistController.swift
//  hello
//
//  Created by 赵康 on 2025/4/13.
//

import Fluent
import FluentSQL
import Redis
import Vapor

struct PlaylistController: RouteCollection, Logging {
  func boot(routes: RoutesBuilder) throws {
    let playlists = routes.grouped("\(RouteEnum.playlists.rawValue)")
    let protected = playlists.grouped(AuthMiddleware())
    
    protected.get("\(RouteEnum.fetch.rawValue)", use: fetchUserPlaylists)
    protected.post("\(RouteEnum.create.rawValue)", use: createPlaylist)
    protected.get(":playlistID", use: getPlaylist)
    protected.put(":playlistID", use: updatePlaylist)
    protected.delete(":playlistID", use: deletePlaylist)
    
    protected.post(":playlistID", "\(RouteEnum.addAudios.rawValue)", use: addAudiosToPlaylist)
    protected.delete(":playlistID", "\(RouteEnum.removeAudios.rawValue)", use: removeAudiosFromPlaylist)
    protected.post(":playlistID", "\(RouteEnum.reorderAudios.rawValue)", use: reorderAudios)
  }
  
  // 获取用户的所有播放列表
  @Sendable
  func fetchUserPlaylists(req: Request) async throws -> [Playlist.Response] {
    let userID = try req.authenticatedUserID
    
    // 尝试从缓存获取
    let cacheKey = CacheConfig.KeyBuilder.playlistsForUser(userID: userID)
    if let cachedPlaylists = try await req.cache.get(
      forKey: cacheKey,
      as: [Playlist.Response].self,
      from: req.redis
    ) {
      return cachedPlaylists
    }
    
    // 从数据库获取
    let playlists = try await Playlist.query(on: req.db)
      .filter(\.$user.$id == userID)
      .filter(\.$isDeleted == false)
      .sort(\.$sortOrder, .ascending)
      .all()
    
    // 转换为响应模型
    let playlistResponses = playlists.map { playlist in
      return Playlist.Response(
        id: playlist.id!,
        name: playlist.name,
        description: playlist.description,
        cover: playlist.cover,
        audioIds: playlist.audioIds,
        audioAddedDates: playlist.audioAddedDates,
        type: playlist.type,
        sortOrder: playlist.sortOrder,
        createdAt: playlist.createdAt,
        updatedAt: playlist.updatedAt
      )
    }
    
    // 缓存结果
    try await req.cache.set(
      playlistResponses,
      forKey: cacheKey,
      duration: CacheConfig.Duration.medium,
      type: .playlist,
      on: req.redis
    )
    
    return playlistResponses
  }
  
  // 创建新播放列表
  @Sendable
  func createPlaylist(req: Request) async throws -> Playlist.Response {
    let userID = try req.authenticatedUserID
    let create = try req.content.decode(Playlist.Create.self)
    
    // 获取用户当前的播放列表数量，用于确定sortOrder
    let playlistCount = try await Playlist.query(on: req.db)
      .filter(\.$user.$id == userID)
      .filter(\.$isDeleted == false)
      .count()
    
    // 创建新播放列表
    let playlist = Playlist(
      name: create.name,
      description: create.description,
      cover: create.cover,
      userID: userID,
      type: .custom,
      sortOrder: playlistCount
    )
    
    try await playlist.save(on: req.db)
    
    // 清除用户播放列表缓存
    let cacheKey = CacheConfig.KeyBuilder.playlistsForUser(userID: userID)
    try await req.cache.delete(forKey: cacheKey, on: req.redis)
    
    return Playlist.Response(
      id: playlist.id!,
      name: playlist.name,
      description: playlist.description,
      cover: playlist.cover,
      audioIds: playlist.audioIds,
      audioAddedDates: playlist.audioAddedDates,
      type: playlist.type,
      sortOrder: playlist.sortOrder,
      createdAt: playlist.createdAt,
      updatedAt: playlist.updatedAt
    )
  }
  
  // 获取单个播放列表详情
  @Sendable
  func getPlaylist(req: Request) async throws -> Playlist.Response {
    let userID = try req.authenticatedUserID
    guard let playlistIDString = req.parameters.get("playlistID"),
          let playlistID = UUID(playlistIDString) else {
      throw Abort(.badRequest, reason: "无效的播放列表ID")
    }
    
    // 尝试从缓存获取
    let cacheKey = CacheConfig.KeyBuilder.playlist(playlistID: playlistID, userID: userID)
    if let cachedPlaylist = try await req.cache.get(
      forKey: cacheKey,
      as: Playlist.Response.self,
      from: req.redis
    ) {
      return cachedPlaylist
    }
    
    // 从数据库获取
    guard let playlist = try await Playlist.query(on: req.db)
      .filter(\.$id == playlistID)
      .filter(\.$user.$id == userID)
      .filter(\.$isDeleted == false)
      .first() else {
      throw Abort(.notFound, reason: "播放列表不存在或已删除")
    }
    
    let response = Playlist.Response(
      id: playlist.id!,
      name: playlist.name,
      description: playlist.description,
      cover: playlist.cover,
      audioIds: playlist.audioIds,
      audioAddedDates: playlist.audioAddedDates,
      type: playlist.type,
      sortOrder: playlist.sortOrder,
      createdAt: playlist.createdAt,
      updatedAt: playlist.updatedAt
    )
    
    // 缓存结果
    try await req.cache.set(
      response,
      forKey: cacheKey,
      duration: CacheConfig.Duration.medium,
      type: .playlist,
      on: req.redis
    )
    
    return response
  }
  
  // 更新播放列表信息
  @Sendable
  func updatePlaylist(req: Request) async throws -> Playlist.Response {
    let userID = try req.authenticatedUserID
    guard let playlistIDString = req.parameters.get("playlistID"),
          let playlistID = UUID(playlistIDString) else {
      throw Abort(.badRequest, reason: "无效的播放列表ID")
    }
    
    let update = try req.content.decode(Playlist.Update.self)
    
    // 查找播放列表
    guard let playlist = try await Playlist.query(on: req.db)
      .filter(\.$id == playlistID)
      .filter(\.$user.$id == userID)
      .filter(\.$isDeleted == false)
      .first() else {
      throw Abort(.notFound, reason: "播放列表不存在或已删除")
    }
    
    // 如果是收藏夹类型，不允许修改名称
    if playlist.type == .favorite && update.name != nil {
      throw Abort(.forbidden, reason: "不能修改收藏夹的名称")
    }
    
    // 更新字段
    if let name = update.name {
      playlist.name = name
    }
    
    if let description = update.description {
      playlist.description = description
    }
    
    if let cover = update.cover {
      playlist.cover = cover
    }
    
    try await playlist.save(on: req.db)
    
    // 清除缓存
    let playlistCacheKey = CacheConfig.KeyBuilder.playlist(playlistID: playlistID, userID: userID)
    try await req.cache.delete(forKey: playlistCacheKey, on: req.redis)
    
    let userPlaylistsCacheKey = CacheConfig.KeyBuilder.playlistsForUser(userID: userID)
    try await req.cache.delete(forKey: userPlaylistsCacheKey, on: req.redis)
    
    return Playlist.Response(
      id: playlist.id!,
      name: playlist.name,
      description: playlist.description,
      cover: playlist.cover,
      audioIds: playlist.audioIds,
      audioAddedDates: playlist.audioAddedDates,
      type: playlist.type,
      sortOrder: playlist.sortOrder,
      createdAt: playlist.createdAt,
      updatedAt: playlist.updatedAt
    )
  }
  
  // 删除播放列表
  @Sendable
  func deletePlaylist(req: Request) async throws -> BasicResponse {
    let userID = try req.authenticatedUserID
    guard let playlistIDString = req.parameters.get("playlistID"),
          let playlistID = UUID(playlistIDString) else {
      throw Abort(.badRequest, reason: "无效的播放列表ID")
    }
    
    // 查找播放列表
    guard let playlist = try await Playlist.query(on: req.db)
      .filter(\.$id == playlistID)
      .filter(\.$user.$id == userID)
      .filter(\.$isDeleted == false)
      .first() else {
      throw Abort(.notFound, reason: "播放列表不存在或已删除")
    }
    
    // 如果是收藏夹类型，不允许删除
    if playlist.type == .favorite {
      throw Abort(.forbidden, reason: "不能删除收藏夹")
    }
    
    // 软删除
    playlist.isDeleted = true
    try await playlist.save(on: req.db)
    
    // 清除缓存
    let playlistCacheKey = CacheConfig.KeyBuilder.playlist(playlistID: playlistID, userID: userID)
    try await req.cache.delete(forKey: playlistCacheKey, on: req.redis)
    
    let userPlaylistsCacheKey = CacheConfig.KeyBuilder.playlistsForUser(userID: userID)
    try await req.cache.delete(forKey: userPlaylistsCacheKey, on: req.redis)
    
    return BasicResponse(success: true, message: "播放列表已删除")
  }
  
  // 添加音频到播放列表
  @Sendable
  func addAudiosToPlaylist(req: Request) async throws -> Playlist.Response {
    let userID = try req.authenticatedUserID
    guard let playlistIDString = req.parameters.get("playlistID"),
          let playlistID = UUID(playlistIDString) else {
      throw Abort(.badRequest, reason: "无效的播放列表ID")
    }
    
    let addAudios = try req.content.decode(Playlist.AddAudios.self)
    
    // 查找播放列表
    guard let playlist = try await Playlist.query(on: req.db)
      .filter(\.$id == playlistID)
      .filter(\.$user.$id == userID)
      .filter(\.$isDeleted == false)
      .first() else {
      throw Abort(.notFound, reason: "播放列表不存在或已删除")
    }
    
    // 确保音频存在
    for audioID in addAudios.audioIds {
      guard try await Audio.query(on: req.db)
        .filter(\.$id == audioID)
        .filter(\.$isDeleted == false)
        .first() != nil else {
        throw Abort(.notFound, reason: "音频ID \(audioID) 不存在或已删除")
      }
    }
    
    // 过滤掉已经在播放列表中的音频
    let newAudioIds = addAudios.audioIds.filter { !playlist.audioIds.contains($0) }
    
    // 添加新的音频，并记录添加日期
    let currentTimestamp = Date().timeIntervalSince1970
    for audioId in newAudioIds {
      playlist.audioIds.insert(audioId, at: 0) // 新音频添加到前面
      playlist.audioAddedDates[audioId.uuidString] = currentTimestamp
    }
    
    try await playlist.save(on: req.db)
    
    // 清除缓存
    let playlistCacheKey = CacheConfig.KeyBuilder.playlist(playlistID: playlistID, userID: userID)
    try await req.cache.delete(forKey: playlistCacheKey, on: req.redis)
    
    let userPlaylistsCacheKey = CacheConfig.KeyBuilder.playlistsForUser(userID: userID)
    try await req.cache.delete(forKey: userPlaylistsCacheKey, on: req.redis)
    
    return Playlist.Response(
      id: playlist.id!,
      name: playlist.name,
      description: playlist.description,
      cover: playlist.cover,
      audioIds: playlist.audioIds,
      audioAddedDates: playlist.audioAddedDates,
      type: playlist.type,
      sortOrder: playlist.sortOrder,
      createdAt: playlist.createdAt,
      updatedAt: playlist.updatedAt
    )
  }
  
  // 从播放列表中移除音频
  @Sendable
  func removeAudiosFromPlaylist(req: Request) async throws -> Playlist.Response {
    let userID = try req.authenticatedUserID
    guard let playlistIDString = req.parameters.get("playlistID"),
          let playlistID = UUID(playlistIDString) else {
      throw Abort(.badRequest, reason: "无效的播放列表ID")
    }
    
    let removeAudios = try req.content.decode(Playlist.AddAudios.self)
    
    // 查找播放列表
    guard let playlist = try await Playlist.query(on: req.db)
      .filter(\.$id == playlistID)
      .filter(\.$user.$id == userID)
      .filter(\.$isDeleted == false)
      .first() else {
      throw Abort(.notFound, reason: "播放列表不存在或已删除")
    }
    
    // 移除指定的音频
    playlist.audioIds.removeAll { removeAudios.audioIds.contains($0) }
    
    // 同时清理不再需要的日期记录
    for audioId in removeAudios.audioIds {
      playlist.audioAddedDates.removeValue(forKey: audioId.uuidString)
    }
    
    try await playlist.save(on: req.db)
    
    // 清除缓存
    let playlistCacheKey = CacheConfig.KeyBuilder.playlist(playlistID: playlistID, userID: userID)
    try await req.cache.delete(forKey: playlistCacheKey, on: req.redis)
    
    let userPlaylistsCacheKey = CacheConfig.KeyBuilder.playlistsForUser(userID: userID)
    try await req.cache.delete(forKey: userPlaylistsCacheKey, on: req.redis)
    
    return Playlist.Response(
      id: playlist.id!,
      name: playlist.name,
      description: playlist.description,
      cover: playlist.cover,
      audioIds: playlist.audioIds,
      audioAddedDates: playlist.audioAddedDates,
      type: playlist.type,
      sortOrder: playlist.sortOrder,
      createdAt: playlist.createdAt,
      updatedAt: playlist.updatedAt
    )
  }
  
  // 重新排序播放列表中的音频
  @Sendable
  func reorderAudios(req: Request) async throws -> Playlist.Response {
    let userID = try req.authenticatedUserID
    guard let playlistIDString = req.parameters.get("playlistID"),
          let playlistID = UUID(playlistIDString) else {
      throw Abort(.badRequest, reason: "无效的播放列表ID")
    }
    
    let reorderRequest = try req.content.decode(Playlist.ReorderAudios.self)
    
    // 查找播放列表
    guard let playlist = try await Playlist.query(on: req.db)
      .filter(\.$id == playlistID)
      .filter(\.$user.$id == userID)
      .filter(\.$isDeleted == false)
      .first() else {
      throw Abort(.notFound, reason: "播放列表不存在或已删除")
    }
    
    // 检查索引是否有效
    for index in reorderRequest.fromIndices {
      guard index >= 0 && index < playlist.audioIds.count else {
        throw Abort(.badRequest, reason: "源索引超出范围")
      }
    }
    
    guard reorderRequest.toIndex >= 0 && reorderRequest.toIndex <= playlist.audioIds.count else {
      throw Abort(.badRequest, reason: "目标索引超出范围")
    }
    
    // 重新排序
    var newAudioIds = playlist.audioIds
    let movedItems = reorderRequest.fromIndices.sorted(by: >).map { newAudioIds.remove(at: $0) }
    
    let insertIndex = min(reorderRequest.toIndex, newAudioIds.count)
    newAudioIds.insert(contentsOf: movedItems.reversed(), at: insertIndex)
    
    // 保存更新后的列表
    playlist.audioIds = newAudioIds
    try await playlist.save(on: req.db)
    
    // 清除缓存
    let playlistCacheKey = CacheConfig.KeyBuilder.playlist(playlistID: playlistID, userID: userID)
    try await req.cache.delete(forKey: playlistCacheKey, on: req.redis)
    
    let userPlaylistsCacheKey = CacheConfig.KeyBuilder.playlistsForUser(userID: userID)
    try await req.cache.delete(forKey: userPlaylistsCacheKey, on: req.redis)
    
    return Playlist.Response(
      id: playlist.id!,
      name: playlist.name,
      description: playlist.description,
      cover: playlist.cover,
      audioIds: playlist.audioIds,
      audioAddedDates: playlist.audioAddedDates,
      type: playlist.type,
      sortOrder: playlist.sortOrder,
      createdAt: playlist.createdAt,
      updatedAt: playlist.updatedAt
    )
  }
}

